package com.zhongke.common.utils

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.Configuration
import android.graphics.PorterDuff
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.os.Build
import android.util.TypedValue
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.CheckResult
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.appcompat.content.res.AppCompatResources
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import com.zhongke.common.R
import com.zhongke.common.base.application.ZKBaseApplication

fun toast(msg: String) {
    ZKToastUtils.showShort(msg)
}

fun toastLong(msg: String) {
    ZKToastUtils.showLong(msg)
}


/**
 * Created by wpt on 2021/8/11.
 * Toast工具类，可以在任何线程进行Toast
 * 内部处理如果不是主线程调用的，则切到主线程调用
 */
object ZKToastUtils {
    private val LOADED_TOAST_TYPEFACE = Typeface.create("sans-serif-condensed", Typeface.NORMAL)
    private var currentTypeface = LOADED_TOAST_TYPEFACE

    private var lastToast: Toast? = null

    const val LENGTH_SHORT = Toast.LENGTH_SHORT
    const val LENGTH_LONG = Toast.LENGTH_LONG
    private var textSize = 15 // in SP
    private var tintIcon = true
    private var allowQueue = false
    private var toastGravity = Gravity.CENTER
    private var xOffset = -1
    private var yOffset = -20
    private var supportDarkTheme = true
    private var isRTL = false

    /**
     * 实际不需要context 这里是为了兼容已有的项目
     * @param context Context?
     * @param msg String
     * @param duration Int
     */
    fun show(msg: String, duration: Int = LENGTH_SHORT) {
        normal(msg, duration).show()
    }

    /**
     * 实际不需要context 这里是为了兼容已有的项目
     * */
    fun show(msg: CharSequence, duration: Int = LENGTH_SHORT) {
        normal(msg, duration).show()
    }

    fun showShort(msg: String?) {
        show(msg ?: "")
    }

    fun showLong(msg: String?) {
        normal(msg ?: "", LENGTH_LONG).show()
    }

    fun showShortCenter(msg: String, duration: Int = LENGTH_SHORT) {
        show(msg, duration)
    }

    @CheckResult
    fun normal(@StringRes message: Int): Toast {
        return normal(
            ZKBaseApplication.getContext().getString(message),
            Toast.LENGTH_SHORT,
            null,
            false
        )
    }

    @CheckResult
    fun normal(message: CharSequence): Toast {
        return normal(message, Toast.LENGTH_SHORT, null, false)
    }

    @CheckResult
    fun normal(@StringRes message: Int, icon: Drawable?): Toast {
        return normal(
            ZKBaseApplication.getContext().getString(message),
            Toast.LENGTH_SHORT,
            icon,
            true
        )
    }

    @CheckResult
    fun normal(message: CharSequence, icon: Drawable?): Toast {
        return normal(message, Toast.LENGTH_SHORT, icon, true)
    }

    @CheckResult
    fun normal(@StringRes message: Int, duration: Int): Toast {
        return normal(ZKBaseApplication.getContext().getString(message), duration, null, false)
    }

    @CheckResult
    fun normal(message: CharSequence, duration: Int): Toast {
        return normal(message, duration, null, false)
    }

    @CheckResult
    fun normal(
        @StringRes message: Int, duration: Int,
        icon: Drawable?
    ): Toast {
        return normal(ZKBaseApplication.getContext().getString(message), duration, icon, true)
    }

    @CheckResult
    fun normal(
        message: CharSequence, duration: Int,
        icon: Drawable?
    ): Toast {
        return normal(message, duration, icon, true)
    }

    @CheckResult
    fun normal(
        @StringRes message: Int, duration: Int,
        icon: Drawable?, withIcon: Boolean
    ): Toast {
        return normalWithDarkThemeSupport(
            ZKBaseApplication.getContext().getString(message),
            icon,
            duration,
            withIcon
        )
    }

    @CheckResult
    fun normal(
        message: CharSequence, duration: Int,
        icon: Drawable?, withIcon: Boolean
    ): Toast {
        return normalWithDarkThemeSupport(message, icon, duration, withIcon)
    }

    // @CheckResult
    // fun warning(@StringRes message: Int): Toast {
    //     return warning( ZKBaseApplication.getContext().getString(message), Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun warning(message: CharSequence): Toast {
    //     return warning(message, Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun warning(@StringRes message: Int, duration: Int): Toast {
    //     return warning( ZKBaseApplication.getContext().getString(message), duration, true)
    // }
    //
    // @CheckResult
    // fun warning(message: CharSequence, duration: Int): Toast {
    //     return warning(message, duration, true)
    // }
    //
    // @CheckResult
    // fun warning(@StringRes message: Int, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //          ZKBaseApplication.getContext().getString(message),
    //         ToastyUtils.getDrawable(R.drawable.ic_error_outline_white_24dp),
    //         ToastyUtils.getColor(R.color.warningColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }
    //
    // @CheckResult
    // fun warning(message: CharSequence, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //         message,
    //         ToastyUtils.getDrawable(R.drawable.ic_error_outline_white_24dp),
    //         ToastyUtils.getColor(R.color.warningColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }
    //
    // @CheckResult
    // fun info(@StringRes message: Int): Toast {
    //     return info( ZKBaseApplication.getContext().getString(message), Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun info(message: CharSequence): Toast {
    //     return info(message, Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun info(@StringRes message: Int, duration: Int): Toast {
    //     return info( ZKBaseApplication.getContext().getString(message), duration, true)
    // }
    //
    // @CheckResult
    // fun info(message: CharSequence, duration: Int): Toast {
    //     return info(message, duration, true)
    // }
    //
    // @CheckResult
    // fun info(@StringRes message: Int, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //          ZKBaseApplication.getContext().getString(message),
    //         ToastyUtils.getDrawable(R.drawable.ic_info_outline_white_24dp),
    //         ToastyUtils.getColor(R.color.infoColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }
    //
    // @CheckResult
    // fun info(message: CharSequence, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //         message, ToastyUtils.getDrawable(R.drawable.ic_info_outline_white_24dp),
    //         ToastyUtils.getColor(R.color.infoColor), ToastyUtils.getColor(R.color.base_color_333333),
    //         duration, withIcon, true
    //     )
    // }
    //
    // @CheckResult
    // fun success(@StringRes message: Int): Toast {
    //     return success( ZKBaseApplication.getContext().getString(message), Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun success(message: CharSequence): Toast {
    //     return success(message, Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun success(@StringRes message: Int, duration: Int): Toast {
    //     return success( ZKBaseApplication.getContext().getString(message), duration, true)
    // }
    //
    // @CheckResult
    // fun success(message: CharSequence, duration: Int): Toast {
    //     return success(message, duration, true)
    // }
    //
    // @CheckResult
    // fun success(@StringRes message: Int, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //          ZKBaseApplication.getContext().getString(message),
    //         ToastyUtils.getDrawable(R.drawable.ic_check_white_24dp),
    //         ToastyUtils.getColor(R.color.successColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }
    //
    // @CheckResult
    // fun success(message: CharSequence, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //         message,
    //         ToastyUtils.getDrawable(R.drawable.ic_check_white_24dp),
    //         ToastyUtils.getColor(R.color.successColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }
    //
    // @CheckResult
    // fun error(@StringRes message: Int): Toast {
    //     return error( ZKBaseApplication.getContext().getString(message), Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun error(message: CharSequence): Toast {
    //     return error(message, Toast.LENGTH_SHORT, true)
    // }
    //
    // @CheckResult
    // fun error(@StringRes message: Int, duration: Int): Toast {
    //     return error( ZKBaseApplication.getContext().getString(message), duration, true)
    // }
    //
    // @CheckResult
    // fun error(message: CharSequence, duration: Int): Toast {
    //     return error(message, duration, true)
    // }
    //
    // @CheckResult
    // fun error(@StringRes message: Int, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //         ZKBaseApplication.getContext().getString(message),
    //         ToastyUtils.getDrawable(R.drawable.ic_clear_white_24dp),
    //         ToastyUtils.getColor(R.color.errorColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }
    //
    // @CheckResult
    // fun error(message: CharSequence, duration: Int, withIcon: Boolean): Toast {
    //     return custom(
    //         message,
    //         ToastyUtils.getDrawable(R.drawable.ic_clear_white_24dp),
    //         ToastyUtils.getColor(R.color.errorColor),
    //         ToastyUtils.getColor(R.color.base_color_333333),
    //         duration,
    //         withIcon,
    //         true
    //     )
    // }

    @CheckResult
    fun custom(
        @StringRes message: Int, icon: Drawable?,
        duration: Int, withIcon: Boolean
    ): Toast {
        return custom(
            ZKBaseApplication.getContext().getString(message),
            icon,
            -1,
            ToastyUtils.getColor(R.color.base_color_333333),
            duration,
            withIcon,
            false
        )
    }

    @CheckResult
    fun custom(
        message: CharSequence, icon: Drawable?,
        duration: Int, withIcon: Boolean
    ): Toast {
        return custom(
            message, icon, -1, ToastyUtils.getColor(R.color.base_color_333333),
            duration, withIcon, false
        )
    }

    @CheckResult
    fun custom(
        @StringRes message: Int, @DrawableRes iconRes: Int,
        @ColorRes tintColorRes: Int, duration: Int,
        withIcon: Boolean, shouldTint: Boolean
    ): Toast {
        return custom(
            ZKBaseApplication.getContext().getString(message), ToastyUtils.getDrawable(iconRes),
            ToastyUtils.getColor(tintColorRes), ToastyUtils.getColor(R.color.base_color_333333),
            duration, withIcon, shouldTint
        )
    }

    @CheckResult
    fun custom(
        message: CharSequence, @DrawableRes iconRes: Int,
        @ColorRes tintColorRes: Int, duration: Int,
        withIcon: Boolean, shouldTint: Boolean
    ): Toast {
        return custom(
            message, ToastyUtils.getDrawable(iconRes),
            ToastyUtils.getColor(tintColorRes), ToastyUtils.getColor(R.color.base_color_333333),
            duration, withIcon, shouldTint
        )
    }

    @CheckResult
    fun custom(
        @StringRes message: Int, icon: Drawable?,
        @ColorRes tintColorRes: Int, duration: Int,
        withIcon: Boolean, shouldTint: Boolean
    ): Toast {
        return custom(
            ZKBaseApplication.getContext().getString(message),
            icon,
            ToastyUtils.getColor(tintColorRes),
            ToastyUtils.getColor(R.color.base_color_333333),
            duration,
            withIcon,
            shouldTint
        )
    }

    @CheckResult
    fun custom(
        @StringRes message: Int, icon: Drawable?,
        @ColorRes tintColorRes: Int, @ColorRes textColorRes: Int, duration: Int,
        withIcon: Boolean, shouldTint: Boolean
    ): Toast {
        return custom(
            ZKBaseApplication.getContext().getString(message),
            icon,
            ToastyUtils.getColor(tintColorRes),
            ToastyUtils.getColor(textColorRes),
            duration,
            withIcon,
            shouldTint
        )
    }

    @SuppressLint("ShowToast")
    @CheckResult
    fun custom(
        message: CharSequence, icon: Drawable?,
        @ColorInt tintColor: Int, @ColorInt textColor: Int, duration: Int,
        withIcon: Boolean, shouldTint: Boolean
    ): Toast {
        val currentToast = Toast.makeText(ZKBaseApplication.getContext(), "", duration)
        val toastLayout: View =
            (ZKBaseApplication.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater)
                .inflate(R.layout.toast_layout, null)
        val toastRoot = toastLayout.findViewById<ConstraintLayout>(R.id.toast_root)
        val toastIcon = toastLayout.findViewById<ImageView>(R.id.toast_icon)
        val toastTextView = toastLayout.findViewById<TextView>(R.id.toast_text)
        toastRoot.setRoundRectBg(
            ZKBaseApplication.getContext().getColor(R.color.base_color_333333)
        )
        var drawableFrame: Drawable

        //        if (shouldTint)
        //            drawableFrame = ToastyUtils.tint9PatchDrawableFrame(tintColor);
        //        else
        //            drawableFrame = ToastyUtils.getDrawable(R.drawable.toast_frame);
        ////        ToastyUtils.setBackground(toastLayout, drawableFrame);
        if (withIcon) {
            requireNotNull(icon) { "Avoid passing 'icon' as null if 'withIcon' is set to true" }
            if (isRTL && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) toastRoot.layoutDirection =
                View.LAYOUT_DIRECTION_RTL
            ToastyUtils.setBackground(
                toastIcon,
                if (tintIcon) ToastyUtils.tintIcon(icon, textColor) else icon
            )
        } else {
            toastIcon.visibility = View.GONE
        }
        toastTextView.text = message
        //        toastTextView.setTextColor(textColor);
        toastTextView.typeface = currentTypeface
        toastTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize.toFloat())
        currentToast.view = toastLayout
        if (!allowQueue) {
            if (lastToast != null) lastToast!!.cancel()
            lastToast = currentToast
        }

        // Make sure to use default values for non-specified ones.
        currentToast.setGravity(
            if (toastGravity == -1) currentToast.gravity else toastGravity,
            if (xOffset == -1) currentToast.xOffset else xOffset,
            if (yOffset == -1) currentToast.yOffset else yOffset
        )
        return currentToast
    }

    private fun normalWithDarkThemeSupport(
        message: CharSequence, icon: Drawable?,
        duration: Int, withIcon: Boolean
    ): Toast {
        return if (supportDarkTheme && Build.VERSION.SDK_INT >= 29) {
            val uiMode: Int = ZKBaseApplication.getContext().resources
                .configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
            if (uiMode == Configuration.UI_MODE_NIGHT_NO) {
                withLightTheme(message, icon, duration, withIcon)
            } else withDarkTheme(
                message,
                icon,
                duration,
                withIcon
            )
        } else {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                withLightTheme(message, icon, duration, withIcon)
            } else {
                withDarkTheme(message, icon, duration, withIcon)
            }
        }
    }

    private fun withLightTheme(
        message: CharSequence, icon: Drawable?,
        duration: Int, withIcon: Boolean
    ): Toast {
        return custom(
            message, icon, ToastyUtils.getColor(R.color.base_color_333333),
            ToastyUtils.getColor(R.color.normalColor), duration, withIcon, true
        )
    }

    private fun withDarkTheme(
        message: CharSequence, icon: Drawable?,
        duration: Int, withIcon: Boolean
    ): Toast {
        return custom(
            message, icon, ToastyUtils.getColor(R.color.normalColor),
            ToastyUtils.getColor(R.color.base_color_333333), duration, withIcon, true
        )
    }

    class Config private constructor() {
        private var typeface = currentTypeface
        private var textSize = ZKToastUtils.textSize
        private var tintIcon = ZKToastUtils.tintIcon
        private var allowQueue = false
        private var toastGravity = ZKToastUtils.toastGravity
        private var xOffset = ZKToastUtils.xOffset
        private var yOffset = ZKToastUtils.yOffset
        private var supportDarkTheme = true
        private var isRTL = false

        @CheckResult
        fun setToastTypeface(typeface: Typeface): Config {
            this.typeface = typeface
            return this
        }

        @CheckResult
        fun setTextSize(sizeInSp: Int): Config {
            this.textSize = sizeInSp
            return this
        }

        @CheckResult
        fun tintIcon(tintIcon: Boolean): Config {
            this.tintIcon = tintIcon
            return this
        }

        @CheckResult
        fun allowQueue(allowQueue: Boolean): Config {
            this.allowQueue = allowQueue
            return this
        }

        @CheckResult
        fun setGravity(gravity: Int, xOffset: Int, yOffset: Int): Config {
            this.toastGravity = gravity
            this.xOffset = xOffset
            this.yOffset = yOffset
            return this
        }

        @CheckResult
        fun setGravity(gravity: Int): Config {
            this.toastGravity = gravity
            return this
        }

        @CheckResult
        fun supportDarkTheme(supportDarkTheme: Boolean): Config {
            this.supportDarkTheme = supportDarkTheme
            return this
        }

        fun setRTL(isRTL: Boolean): Config {
            this.isRTL = isRTL
            return this
        }

        fun apply() {
            currentTypeface = typeface
            ZKToastUtils.textSize = textSize
            ZKToastUtils.tintIcon = tintIcon
            ZKToastUtils.allowQueue = allowQueue
            ZKToastUtils.toastGravity = toastGravity
            ZKToastUtils.xOffset = xOffset
            ZKToastUtils.yOffset = yOffset
            ZKToastUtils.supportDarkTheme = supportDarkTheme
            ZKToastUtils.isRTL = isRTL
        }

        companion object {
            @get:CheckResult
            val instance: Config
                get() = Config()

            fun reset() {
                currentTypeface = LOADED_TOAST_TYPEFACE
                textSize = 16
                tintIcon = true
                allowQueue = false
                toastGravity = Gravity.CENTER
                xOffset = -1
                yOffset = -1
                supportDarkTheme = true
                isRTL = false
            }
        }
    }

    internal object ToastyUtils {
        fun tintIcon(drawable: Drawable, @ColorInt tintColor: Int): Drawable {
            drawable.setColorFilter(tintColor, PorterDuff.Mode.SRC_IN)
            return drawable
        }

        //        static Drawable tint9PatchDrawableFrame(@ColorInt int tintColor) {
        //            final NinePatchDrawable toastDrawable = (NinePatchDrawable) getDrawable(R.drawable.toast_frame);
        //            return tintIcon(toastDrawable, tintColor);
        //        }
        fun setBackground(view: View, drawable: Drawable?) {
            //            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
            //                //view.setBackground(drawable);
            //            else
            ////                view.setBackgroundDrawable(drawable);
        }

        fun getDrawable(@DrawableRes id: Int): Drawable? {
            return AppCompatResources.getDrawable(ZKBaseApplication.getContext(), id)
        }

        fun getColor(@ColorRes color: Int): Int {
            return ContextCompat.getColor(ZKBaseApplication.getContext(), color)
        }
    }
}